package proxy;

import java.lang.reflect.*;
import java.util.*;

/**
 * This program demonstrates the use of proxies.
 * @author andy
 */
public class ProxyTest {

    public static void main(String[] args) {

        Object[] elements = new Object[1000];

        // Fill elements with proxies for the integers 1 ... 1000.
        for (int i = 0; i < elements.length; i++) {
            Integer value = i + 1;
            InvocationHandler handler = new TraceHandler(value);
            Object proxy = Proxy.newProxyInstance(null, new Class[] { Comparable.class }, handler);
            elements[i] = proxy;
        }

        // Construct a random integer.
        Integer key = new Random().nextInt(elements.length) + 1;

        // Search for the key.
        int result = Arrays.binarySearch(elements, key);

        // Print match if found.
        if (result >= 0) {
            System.out.println(elements[result]);
        }
    }
}


/**
 * An invocation handler that prints out the method name and parameters, then invokes the original method.
 */
class TraceHandler implements InvocationHandler {

    private Object target;

    /**
     * Constructs a TraceHandler
     * @param t the implicit parameter of the method call.
     */
    public TraceHandler(Object target) {

        this.target = target;
    }


    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.print(this.target); // Print implicit argument.
        System.out.print("." + method.getName() + "("); // Print method name.

        if (args != null) { // Print explicit arguments.
            for (int i = 0; i < args.length; i++) {
                System.out.print(args[i]);
                if (i < args.length - 1)
                    System.out.print(", ");
            }
        }

        System.out.println(")");

        // Invoke actual method.
        return method.invoke(target, args);
    }
}
